<?php

namespace App\Services\Auth;

use App\Models\User;
use App\Services\BaseServices;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\Request;
use RuntimeException;

class UserServices extends BaseServices
{

    /**
     * 登录.
     *
     * @param Request $request
     * @return array|false
     */
    public function login(Request $request): bool|array
    {
        $nickName = $request->integer('nick_name');

        $userInfo = User::query()->where(['nick_name' => $nickName])->first();

        if (!$userInfo) {
            $this->setCustomError('账号密码错误');
            return false;
        }

        return [
            'token' => $userInfo->createToken('token')->plainTextToken,
            'userInfo' => $userInfo
        ];
    }

    /**
     * 微信登录.
     *
     * @param Request $request
     * @return array|false
     */
    public function wxLogin(Request $request): bool|array
    {
        $code = $request->input('code');

        $params = [
            'appid' => config('wechat.appid'),
            'secret' => config('wechat.secret'),
            'js_code' => $code,
            'grant_type' => 'authorization_code'
        ];

        try {
            $res = $this->wechatLogin($params);

            if (array_key_exists('errcode', $res)) {
                $this->setCustomError('授权失败');
                return false;
            }

            $openId = $res['openid'];

            //判断是否存在用户
            $check = User::query()->where(['openid' => $openId])->first();
            if (!$check) {
                $check = $this->generateUser($openId);
                if ($check === false) {
                    $this->setCustomError('登录失败');
                }
            }

        } catch (RuntimeException $e) {
            $this->setCustomError('授权失败');
            return false;
        }

        return [
            'token' => $check->createToken('token')->plainTextToken,
            'userInfo' => $check
        ];
    }

    /**
     * 微信请求.
     *
     * @param $params
     * @return mixed
     */
    protected function wechatLogin($params): mixed
    {
        $url = '/sns/jscode2session';
        $sendUrl = config('wechat.base_url') . $url;
        try {
            $client = new Client();
            $arrParams = [];
            $arrParams['query'] = $params;
            $response = $client->request('GET', $sendUrl, $arrParams);
        } catch (GuzzleException $e) {
            app('log')->error('请求微信接口发生错误', [
                'code' => $e->getCode(),
                'msg' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'url' => $url,
                'params' => $params,
            ]);

            throw new RuntimeException('微信接口请求失败');
        }

        $jsonResponse = json_decode($response->getBody()->getContents(), true);

        if ($jsonResponse === '') {
            app('log')->error('微信接口返回格式不正确', [
                'url' => $sendUrl,
                'params' => $arrParams,
                'response' => $jsonResponse
            ]);

            throw new RuntimeException('微信返回格式不正确');
        }

        return $jsonResponse;
    }

    /**
     * 创建用户.
     *
     * @param string $openId
     * @return User|false
     */
    protected function generateUser(string $openId)
    {
        $model = new User();

        try {
            $model->nick_name = '用户-' . (10000 + User::query()->max('id'));
            $model->openid = $openId;
            $model->save();
        } catch (Exception $e) {
            $this->setCustomError('登录失败');
            return false;
        }

        return $model;
    }
}
